package com.kotlin.lib.reflect

import kotlin.reflect.KMutableProperty
import kotlin.reflect.full.functions
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible

fun main() {
//    reflectByNoArgumentConstructor()

    val reflectBean = reflectByArgument()
    println("${reflectBean.age} ${reflectBean.name}")
    println("--------------------------------")

    getAndUpdateProperty(reflectBean)
    println("--------------------------------")
    val apply = getAndInokeMethod(reflectBean)
    println(apply)
}

private fun getAndInokeMethod(reflectBean: ReflectBean): Any? {
    val apply = ReflectBean::class.functions.filter { kFunction ->
        kFunction.name == "printInfo"
    }[0].let {
        it.isAccessible = true//private方法
        it.call(reflectBean, " append extra info")
    }
    return apply
}

private fun getAndUpdateProperty(reflectBean: ReflectBean) {
    ReflectBean::class.memberProperties.find {
        it.name == "age"
    }?.apply {
        println("apply get=${get(reflectBean)}")
        if (this is KMutableProperty<*>) {
            setter.call(reflectBean, 51)
            println("update to=${get(reflectBean)}")
        }
    }
    println("${reflectBean.age} ${reflectBean.name}")
}

private fun reflectByArgument(): ReflectBean {
    return ReflectBean::class.constructors.filter { kFunction ->
        kFunction.parameters.size == 2
    }.map {
        it.call("zhangsan", 34)
    }[0]
}

private fun reflectByNoArgumentConstructor() {
    val map: ReflectBean = ReflectBean::class.constructors.filter { kFunction ->
        kFunction.parameters.isEmpty()
    }.map { defaultConstructor ->
        val apply = defaultConstructor.call().apply {
            name = "reflect"
            age = 23
        }
        apply
    }[0]
    println("${map.age} ${map.name}")
}